package code.example.service.admin;

import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import code.example.service.Category;
import code.example.service.Link;

import com.googlecode.cswish.Config;
import com.googlecode.cswish.model.PageElement;
import com.googlecode.cswish.struts.conversion.CommonElementConverter;
import com.googlecode.cswish.struts.conversion.ConversionContext;
import com.googlecode.cswish.struts.conversion.AutoPageConverterManager;
import com.googlecode.cswish.struts.spring.ObjectFactory;

/**
 * List all the possible URLs
 * 	 
 * @author jerry.feng Date: 2008-12-26
 */
public class SiteMap {

	@Resource
	private Config config;
	
	@Resource
	private ObjectFactory objectFactory;

	@Resource
	AutoPageConverterManager converterManager;
	
	public List<Object> showAll() {
		converterManager.registerConverter(Link.class.getName(), new CommonElementConverter() {
			@Override
			public PageElement convert(ConversionContext context) {
				PageElement element = super.convert(context);
				element.setType("link.ftl");
				return element;
			}
		});
		
		// Convert file structure to Category
		// Directory <--> Category
		// File + Operation <--> Link
		List<Object> categoryList = new ArrayList<Object>();
		
		String modelDir = getPackageDir(config.getModelPackage());
		addToFileList(categoryList, modelDir.length(), new File(modelDir));
		String serviceDir = getPackageDir(config.getServicePackage());
		addToFileList(categoryList, serviceDir.length(), new File(serviceDir));
		
		// TODO: remove blank directory
		return categoryList;
	}
	
	private String getPackageDir(String packageName) {
		String baseDir = this.getClass().getResource("/").getFile();
		return new File(baseDir + packageName.replace('.', '/')).getPath();
	}
	
	private void addToFileList(List<Object> fileList, int prefix, File file) {
		if (file.isDirectory()) {
			File[] files = file.listFiles(new FileFilter() {
				@Override
				public boolean accept(File pathname) {
					return pathname.isDirectory() || pathname.getName().endsWith(".class");
				}
			});
			
			for (File subFile : files) {
				if (subFile.isDirectory()) {
					Category category = indexOf(fileList, subFile.getName());
					if (category == null) {
						category = new Category();
						String dir = subFile.getPath().substring(prefix);
						category.setDir(dir);
						category.setCaption(subFile.getName());
						fileList.add(category);
					}
					addToFileList(category.getItems(), prefix, subFile);
				} else {
					String fileName = subFile.getPath().substring(prefix + 1);
					String className = fileName.substring(0, fileName.length() - 6)
								.replace(File.separatorChar, '.');
					
					// Build a link: parent directory + current model name + operation
					// TODO: get all the permitted public method
					String link = '/' + className.replace('.', '/') + '.' + "search";
					fileList.add(new Link(subFile.getName(), link));
				}
			}
		}
	}
	
	private Category indexOf(List<Object> list, String name) {
		for (Object obj : list) {
			if (obj instanceof Category) {
				Category category = (Category) obj;
				if (name.equals(category.getCaption())) {
					return category;
				}
			}
		}
		return null;
	}
}